﻿//1st Implemented Mode seems to work correctly

//TODO: DistanceFilter: implement other modes and test, speed up


using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Drawing;
using System.Drawing.Imaging;
using System.Linq;
using System.Reflection;
using System.Windows.Forms;

namespace LowLevelGraphics.Filter
{
    /// <summary>
    /// Filter mode
    /// </summary>
    public enum DISTANCE_MODE
    {
        /// <summary>
        /// 
        /// </summary>
        CUSTOM
    }

    /// <summary>
    /// The distance filter calculates 
    /// </summary>
    public class DistanceFilter : BaseImageFilter
    {
        protected DISTANCE_MODE M_DISTANCEMODE = DISTANCE_MODE.CUSTOM;

        /// <summary>
        /// default constructor
        /// </summary>
        public DistanceFilter()
            : this(DISTANCE_MODE.CUSTOM)
        {
        }

        /// <summary>
        /// specify distance mode directly
        /// </summary>
        /// <param name="_MODE"></param>
        public DistanceFilter(DISTANCE_MODE _MODE)
        {
            M_DISTANCEMODE = _MODE;
        }

        /// <summary>
        /// used by clone
        /// </summary>
        /// <param name="_distanceFilter"></param>
        internal DistanceFilter(DistanceFilter _distanceFilter)
        {
            this.M_DISTANCEMODE = _distanceFilter.M_DISTANCEMODE;
        }

        /// <summary>
        /// gets or sets distance mode
        /// </summary>
        public DISTANCE_MODE DistanceMode
        {
            get { return M_DISTANCEMODE; }
            set { M_DISTANCEMODE = value; }
        }

        //TODO: speed up this loop
        //normally 9x times faster should be possible
        /// <summary>
        /// executes this filter
        /// </summary>
        /// <param name="_bitmap"></param>
        /// <returns></returns>
        public override UnsafeBitmap Execute(UnsafeBitmap _bitmap)
        {
            Color[] aColor = new Color[8];
            List<Point> aPoint = Definitions.EnvironmentPointList;
            double dSum = 0;
            List<int> aInt = new List<int>();
            double dAverage = 0.0f;
            double dDistanceMax = ColorFunctions.MaxDistance();
            int nColorArrayLength = aColor.Length;

            Dictionary<Point, Color> aColorPoint = new Dictionary<Point, Color>();

            int nWidth = _bitmap.Width;
            int nHeight = _bitmap.Height;

            Color color = Color.Transparent;
            Color colorConvert = Color.Transparent;

            int y = 0;
            int x = 0;
            for (y = 0; y < nHeight; y++)
            {
                for (x = 0; x < nWidth; x++)
                {
                    color = _bitmap.GetPixel(x, y);
                    aColor = Segmentation.GetEnvironmentPixelColorArray(_bitmap, x, y, aPoint, aColor);
                    dSum = 0;
                    foreach (Color colorTemp in aColor)
                    {
                        dSum += ColorFunctions.Distance(colorTemp, color);
                    }
                    dAverage = (double)(dSum / nColorArrayLength / (255.0f / dDistanceMax));
                    int nValue = (int)dAverage;
                    if (nValue >= 255)
                    {
                        aInt.Add(nValue);
                        nValue = 255;
                    }
                    colorConvert = Color.FromArgb(nValue, nValue, nValue);
                    aColorPoint.Add(new Point(x, y), colorConvert);
                }
            }

            aInt.Sort();

            Point ptPoint = Point.Empty;
            foreach (KeyValuePair<Point, Color> keyValuePair in aColorPoint)
            {
                ptPoint = keyValuePair.Key;
                _bitmap.SetPixel(ptPoint.X, ptPoint.Y, keyValuePair.Value);
            }
            return _bitmap;
        }

        /// <summary>
        /// used to create a deep copy
        /// </summary>
        /// <returns></returns>
        public override object Clone()
        {
            return new DistanceFilter(this);
        }
    }
}
